package com.hzhq.contract.service.impl;

import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSONObject;
import com.hzhq.contract.bean.dto.UserDTO;
import com.hzhq.contract.bean.entity.*;
import com.hzhq.contract.bean.vo.UserVO;
import com.hzhq.contract.convert.UserConvertBasic;
import com.hzhq.contract.repo.*;
import com.hzhq.contract.result.Result;
import com.hzhq.contract.result.ResultEnum;
import com.hzhq.contract.service.UserService;
import com.hzhq.contract.status.BaseStatus;
import com.hzhq.contract.status.DefaultValue;
import com.hzhq.contract.util.Page2ResultUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author hzhq
 * @create 2021/3/23 5:51 下午
 * @email hzhq1255@163.com
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private AdminRepository adminRepository;

    @Autowired
    private DepartRepository departRepository;

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private UserRoleRepository userRoleRepository;


    @Autowired
    private MongoTemplate mongoTemplate;

    private Boolean checkIsRegistered(String userName) {
        return null != userName && userRepository.findByUsernameAndDeleted(userName, DefaultValue.NOT_DELETED).isPresent();
    }

    private Integer checkAdminIsExisted(String adminName, Depart depart, Integer type) {
        Integer flag = -1;
        if (type == 0) {
            if (adminRepository.findByAdminNameAndDeleted(adminName, DefaultValue.NOT_DELETED).isPresent()) {
                flag = 0;
            }
        }
//        if (type == 1){
//            UserRole userRole =
//                    userRoleRepository.findByUserAndDepartAndDeletedAndPassed(adminName,depart,DefaultValue.NOT_DELETED,DefaultValue.PASSED_REVIEW);
//            if (userRole != null && userRole.getRole().getRoleType() == 0) {
//                flag = 1;
//            }
//        }
        return flag;
    }

    @Override
    public Result<Object> loginCheck(String username, String password, Integer type) {
        Result<Object> result = Result.build(ResultEnum.USER_LOGIN_SUCCESS);
        Admin loginAdmin = new Admin();
        User loginUser = new User();
        switch (type) {
            case 0:
                loginAdmin = adminRepository.findByAdminNameAndDeleted(username, DefaultValue.NOT_DELETED).orElse(null);
                if (null == loginAdmin) {
                    return Result.build(ResultEnum.USER_NOT_EXIST);
                }
                break;
            case 1:
                loginUser = userRepository.findByUsernameAndDeleted(username, DefaultValue.NOT_DELETED).orElse(null);
                if (null == loginUser) {
                    return Result.build(ResultEnum.USER_NOT_EXIST);
                }
                break;
            default:
                return Result.build(ResultEnum.USER_LOGIN_ERROR);
        }
        String md5pwd = SecureUtil.md5(password);
        if (md5pwd.equals(loginAdmin.getPassword()) && type == 0) {
            result.setData(loginAdmin.getAdminId().toString());
            return result;
        }
        if (md5pwd.equals(loginUser.getPassword()) && type == 1) {
            result.setData(loginUser.getUserId().toString());
            return result;
        }

        result = Result.build(ResultEnum.USER_LOGIN_ERROR);
        return result;
    }

    @Override
    public Result<Object> registerUser(UserDTO user) {
        if (checkIsRegistered(user.getUsername())) {
            return Result.build(ResultEnum.USER_IS_EXISTED);
        }
        try {
            userRepository.save(UserConvertBasic.INSTANCE.dtoToPo(user));
        } catch (Exception e) {
            return Result.build(ResultEnum.USER_REGISTER_ERROR);
        }
        return Result.build(ResultEnum.USER_REGISTER_SUCCESS);
    }

    @Override
    public Page<UserDTO> getAll(Pageable pageable) {
        Page<UserDTO> userPage = userRepository.findByDeleted(DefaultValue.NOT_DELETED, pageable)
                .map(UserConvertBasic.INSTANCE::poToDto);
        return userPage;
    }

    @Override
    public Result<Object> getAllUserList() {
        List<UserDTO> userDTOList = userRepository.findAll().stream().map(UserConvertBasic.INSTANCE::poToDto).collect(Collectors.toList());
        return Result.success(userDTOList.stream().map(UserConvertBasic.INSTANCE::dtoToVo).collect(Collectors.toList()));
    }

    @Override
    public Result<Object> searchByUsername(String username, Pageable pageable) {

        Page<UserDTO> userPage = userRepository.findAllByUsernameLikeAndDeleted(username, DefaultValue.NOT_DELETED, pageable);
        Page<UserVO> userVOPage = userPage.map(UserConvertBasic.INSTANCE::dtoToVo);
        return Result.success(Page2ResultUtil.getPageData(userVOPage));
    }

    @Override
    public Result<Object> applicantRole(String username, String roleName, String departName,
                                        String adminName, Integer type, Integer passed) {
//
//        Optional<Role> roleOptional = roleRepository.findByRoleNameAndDeleted(roleName,DefaultValue.NOT_DELETED);
//        Optional<Depart> departOptional = departRepository.findByDepartNameAndDeleted(departName,DefaultValue.NOT_DELETED);
//        Role role = roleOptional.orElseGet(Role::new);
//        Depart depart = departOptional.orElseGet(Depart::new);
//        User user = userRepository.findUserByUsernameAndDeleted(username,DefaultValue.NOT_DELETED);
//
//        if (null == adminName && null == type){
//            passed = 0;
//            UserRole userRole = new UserRole();
//            userRole.setUser(username);
//            userRole.setRole(role);
//            userRole.setDepart(depart);
//            userRole.setPassed(passed);
//            userRole.setDeleted(DefaultValue.NOT_DELETED);
//            userRoleRepository.save(userRole);
//            log.info("User applicantRole username: {}, roleName: {}, departName: {}, passed: {}",
//                    username,roleName,departName,passed);
//            return Result.success("申请成功，请等待管理员处理");
//        }
//        if (null != adminName && null != type && null != passed){
//            Integer flag = checkAdminIsExisted(adminName,depart,type);
//            if (passed != 0 && flag != -1){
//                UserRole userRole = userRoleRepository.findByUserAndRoleAndDepartAndPassedAndDeleted(
//                        username,role,depart,DefaultValue.NOT_PASSED,DefaultValue.NOT_DELETED
//                );
//                if (null == userRole){
//                    return Result.error("该用户没有申请");
//                }
//                switch (flag){
//                    case 0:
//                        userRole.setAdminType(DefaultValue.SYSTEM_ADMIN);break;
//                    case 1:
//                        if (role.getRoleType() == 0){
//                            return Result.error("部门管理员权限只能由系统管理员授予");
//                        }
//                        userRole.setAdminType(DefaultValue.DEPART_ADMIN);break;
//                    default:break;
//                }
//                userRole.setAdmin(adminName);
//                userRole.setAdminType(type);
//                userRole.setPassed(passed);
//                userRole.setAssignTime(new Date());
//                userRole = userRoleRepository.save(userRole);
//                log.info("User applicantRole username: {}, roleName: {}, departName: {}, passed: {}, adminName: {}, adminType: {}",
//                        username,roleName,departName,passed,adminName,type);
//                if (passed == 1){
//                    if (user.getRoleList() == null){
//                        user.setRoleList(new ArrayList<>());
//                    }
//                    user.getRoleList().add(userRole);
//                    userRepository.save(user);
//                    return Result.success("批准成功");
//                }
//                if (passed == -1){
//                    return Result.success("拒绝通过");
//                }
//                return Result.error("申请操作出现错误");
//            }
//        }

        return Result.error("没有权限");
    }

    @Override
    public UserDTO getOneByName(String username) {
        Optional<User> userOptional = userRepository.findByUsernameAndDeleted(username, DefaultValue.NOT_DELETED);
        return userOptional.map(UserConvertBasic.INSTANCE::poToDto).orElse(null);
    }


    @Override
    public Page<UserDTO> searchAllPages(UserDTO userDTO, Integer currentPage, Integer pageSize) {
        User user = UserConvertBasic.INSTANCE.dtoToPo(userDTO);
        user.setDeleted(DefaultValue.NOT_DELETED);
        Pageable pageable = Page2ResultUtil.buildPageableByParam(currentPage, pageSize,
                Sort.by(Sort.Direction.DESC, "userId"));
        ExampleMatcher exampleMatcher = ExampleMatcher.matching()
                .withMatcher("username", ExampleMatcher.GenericPropertyMatchers.contains())
                .withMatcher("phone", ExampleMatcher.GenericPropertyMatchers.contains());
        Example<User> userExample = Example.of(user, exampleMatcher);
        return userRepository.findAll(userExample, pageable).map(UserConvertBasic.INSTANCE::poToDto);
    }

    @Override
    public Page<UserDTO> searchAllPages(Query query, Integer currentPage, Integer pageSize) {
        Pageable pageable = Page2ResultUtil.buildPageableByParam(currentPage, pageSize, Sort.by(Sort.Direction.DESC, User.USERID_FIELD));
        long count = mongoTemplate.count(query, User.class);
        List<User> users = mongoTemplate.find(query.with(pageable), User.class);
        List<UserDTO> userDTOs = users.stream().map(UserConvertBasic.INSTANCE::poToDto).collect(Collectors.toList());
        return new PageImpl<>(userDTOs, pageable, count);
    }

    @Override
    public String save(UserDTO userDTO) {
        User user = UserConvertBasic.INSTANCE.dtoToPo(userDTO);
        return userRepository.save(user).getUserId().toString();
    }
}